Greengrass Lambdaから使える環境変数について調べてみた
はじめに
サーバーレス開発部@大阪の岩田です。 AWS Lambdaの実行環境で利用できる環境変数については公式ドキュメントに記載がありますが、GreengrassのCoreデバイス上で動作するGreengrass Lambdaについては環境変数に関する情報が特に見つかりませんでした。
自分用のメモとしてGreengrass Lambdaから利用できる環境変数について調べてみたので、内容をご紹介します。
環境変数をログに出力して確認してみる
環境変数を出力するだけの簡単なLambdaを作成し、Greengrassグループにデプロイ&実行してみます。Python2.7で実装しています。
import os def lambda_handler(event, context): print(os.environ)
Greengrassグループにデプロイ&実行すると/greengrass/ggc/var/log/user/<リージョン>/<AWSアカウントID>/<Lambda関数名>
にログが出力されます。ログに出力された環境変数をJSONに整形すると以下のようになりました。
{ "AWS_CONTAINER_AUTHORIZATION_TOKEN": "Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx", "AWS_CONTAINER_CREDENTIALS_FULL_URI": "http://localhost:8000/2016-11-01/credentialprovider/", "AWS_DEFAULT_REGION": "ap-northeast-1", "AWS_GG_FIPS_MODE": "false", "AWS_GG_HTTP_ENDPOINT": "greengrass-ats.iot.ap-northeast-1.amazonaws.com:8443", "AWS_GG_MQTT_ENDPOINT": "greengrass-ats.iot.ap-northeast-1.amazonaws.com:8883", "AWS_IOT_HTTP_ENDPOINT": "xxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com:8443", "AWS_IOT_MQTT_ENDPOINT": "xxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com:8883", "AWS_IOT_THING_NAME": "CM-Iwata-GGGroup_Core", "AWS_REGION": "ap-northeast-1", "ENCODING_TYPE": "json", "GGC_MAX_INTERFACE_VERSION": "1.2", "GG_MQTT_CONNECT_MAX_RETRY_INTERVAL": "60", "GG_MQTT_CONNECT_TIMEOUT": "30", "GG_MQTT_KEEP_ALIVE": "60", "HOME": "/lambda", "IPC_SOCK_FILE": "/greengrass_ipc.sock", "LOG_LEVEL": "INFO", "MY_FUNCTION_ARN": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:CM-IwataPrintEnvVar:1", "PATH": "/usr/bin:/usr/local/bin", "PYTHONPATH": "/lambda", "ROUTER_FUNCTION_ARN": "arn:aws:lambda:::function:GGRouter", "SECRETS_MANAGER_FUNCTION_ARN": "arn:aws:lambda:::function:GGSecretManager:1", "SHADOW_FUNCTION_ARN": "arn:aws:lambda:::function:GGShadowService", "_GG_LOG_FD_DEBUG": "3", "_GG_LOG_FD_ERROR": "2", "_GG_LOG_FD_FATAL": "5", "_GG_LOG_FD_INFO": "1", "_GG_LOG_FD_WARN": "4" }
名前から察するにAWS_IOT_THING_NAME
にはCoreデバイスのモノの名前が入っていそうです。
またGG_MQTT_CONNECT_MAX_RETRY_INTERVAL
やGG_MQTT_KEEP_ALIVE
はGreengrassの設定ファイルconfig.json
で設定した値がセットされていそうです。
他の環境変数に関しても、なんとなく名前から設定値の意味が読み取れます。
こうしてみると同じLambdaとはいえ通常のAWS LambdaとGreengrass Lambdaでは環境変数の中身が結構違いますね。
Greengrass Lambdaの裏側を少しのぞいて見る
せっかくなのでGreengrass Lambdaの環境変数から取得した情報で少し遊んでみます。
環境変数AWS_CONTAINER_CREDENTIALS_FULL_URI
に入っているURLに対しておもむろにリクエストを投げてみます。
$ curl http://localhost:8000/2016-11-01/credentialprovider/ Request is missing auth token
どうも認証が必要なようです。AWS_CONTAINER_AUTHORIZATION_TOKEN
という環境変数にいかにもな文字列が入っているので、今度はAuthorization
ヘッダに環境変数AWS_CONTAINER_AUTHORIZATION_TOKEN
の値を入れてリクエストしてみます。
$ curl http://localhost:8000/2016-11-01/credentialprovider/ -H "Authorization: Basic xxxxxxxxxx" {\n \"Message\" : \"You need to attach an IAM role to this deployment group.\"\n}
エラーメッセージが変わりました。今度はちゃんと認証できているようですが、IAMロールをアタッチしろ!と怒られています。そういえばLambdaをデプロイしたGreengrassグループにIAMロールをアタッチしていませんでした。IAMロールをアタッチしてから再度試してみます。
$ curl http://localhost:8000/2016-11-01/credentialprovider/ -H "Authorization: Basic xxxxxxxxxx" {"AccessKeyId":"xxxxxxxxxx","SecretAccessKey":"xxxxxxxxxx","Token":"xxxxxxxxxx","Expiration":"2019-03-22T03:26:06Z"}
何やらAWSのアクセスキーが払い出されました。このアクセスキーを使ってAWS CLIを叩いてみましょう。
$ export AWS_ACCESS_KEY_ID=xxxxxxxxxx $ export AWS_SECRET_ACCESS_KEY=xxxxxxxxxx $ export AWS_SESSION_TOKEN=xxxxxxxxxx $ aws sts get-caller-identity { "Account": "<AWSアカウントID>", "UserId": "xxxxxxxxx:GreenGrassSession", "Arn": "arn:aws:sts::<AWSアカウントID>:assumed-role/<Greengrassグループにアタッチしたロール名>/GreenGrassSession" }
こんな結果が返ってきました。
ここまでの動きを見る限り、環境変数AWS_CONTAINER_CREDENTIALS_FULL_URI
で定義されたエンドポイントに対して認証情報付きのリクエストを発行することで、GreengrassグループにアタッチしたロールにAssume Roleするためのクレデンシャルを取得できるようです。
Greengrass LambdaがAWSのサービスにアクセスする際の裏側の動作が少し垣間見えました。
まとめ
Greengrass Lambdaから利用できる環境変数について公式ドキュメントが見当たらなかったので、備忘も兼ねてブログにまとめてみました。 元々はGreengrass LambdaからCoreデバイスのモノの名前を取得するにはどうしたら良いんだっけ?というところから調べ始めたのですが、とりあえず目的は達成できたので良かったです。 誰かの参考になれば幸いです。